/* RMORPG - Server.cpp
   Copyright (c) 2007, Michael Borgmann <code@lechuck.de>
   This code is released under the GNU Public License (GPL)
 */

#include <iostream>
#include "Server.h"

using namespace std;
using namespace rmorpg;

// Create listening Server
bool Server::Listening() {

	// Create Socket
	std::cout << "Create TCP Socket ... ";
	if (listener.CreateTCPSocket()) std::cout << "yes\n";
	else return false;

	// Bind Socket
	std::cout << "Bind Socket ... ";
	if (listener.Bind(6666)) std::cout << "yes\n";
	else return false;

	// Listener
	std::cout << "Listen to Socket ... ";
	if (listener.Listen(16)) std::cout << "yes\n";
	else return false;


	// no errors
	return true;
}

// Multiplexing
bool Server::Multiplexing() {

	// clear socket set
	FD_ZERO(&sockets);

	// add listener to socket set
	FD_SET(listener.Get(), &sockets);

	// add all connections to socket set
	for (socket = connection.begin(); socket != connection.end(); socket++)
		FD_SET(*socket, &sockets);

	// check for active sockets
	activity = select(0x7FFFFFFF, &sockets, NULL, NULL, &timeout);

	// any activity?
	if (activity > 0) {

		// check for incoming connections
		if (FD_ISSET(listener.Get(), &sockets)) {

			// incoming connection
			incoming = accept(listener.Get(),
			                  (sockaddr*)&socketaddress,
			                  &sa_size);

			// add socket to list
			connection.push_back(incoming);
		}

		// check connections for activity
		for (socket = connection.begin(); socket != connection.end(); socket++) {

			if (FD_ISSET(*socket, &sockets)) {

				// incoming data
				bytes = recv (*socket, buffer, 128, 0);

				// quit on error
				if (bytes == -1) {
					cout << "Socket receiving error!\n";
					return 0;
				}

				// disconnect socket
				if (bytes == 0 ) {
					shutdown(*socket, 2);
					close(*socket);
					connection.erase(socket);
					socket--;
				}

				else {
					cout << "Data: " << buffer << endl;
					if (strcmp(buffer, "servquit") == 0)
						done = true;
				}
			}
		}
	}
}

// Default Constructor
Server::Server() {	// FIXME

	// no wait state for select()
	timeout.tv_sec = timeout.tv_usec = 0;

	// Start listening server
	if (Listening())
		std::cout << "Server running!" << std::endl;
	else {		// FIXME
		std::cout << "Couldn't create server!" << std::endl;
		exit(1);
	}


	sa_size = sizeof(sockaddr_in);

	done = false;

	// Multiplexer
	while (!done) {
		Multiplexing();
	}
}

// Default Destructor
Server::~Server() {
		shutdown(listener.Get(), 2);
		close(listener.Get());

		for (i = 0; i < connection.size(); i++) {
			shutdown(connection[i], 2);
			close(connection[i]);
		}

}

// M A I N   F U N C T I O N
// * * * RMORPG Server * * *
int main() {

	// RMORPG Server Header
	cout << "RMORPG Test Server\n" << endl;
	cout << "Copyright (c) 2007, "
	     << "Michael Borgmann <code@lechuck.de>" << endl;
	cout << "This project is released under the GNU Public License (GPL)\n"
	     << endl;

	Server rolemaster;
}
